home *** CD-ROM | disk | FTP | other *** search
Text File | 1992-07-15 | 12.1 KB | 448 lines | [TEXT/MPS ] |
- //=======================================================================================
- //
- // SHDemo.c - an application to demonstrate the use of the Asynchronous Sound Helper
- //
- // Written by Bryan K. Ressler (Beaker), 2/4/92
- //
- // Version 1.00, 2/4/92 Original version
- // 1.10, 4/11/92 Integrate final Sound Helper, clean up
- //
- //=======================================================================================
-
- //=======================================================================================
- // Includes
- //=======================================================================================
- #include "Std.h"
- #include "SHDemo.h"
- #include "SoundHelper.h"
-
- //=======================================================================================
- // Globals
- //=======================================================================================
- Boolean gHelperNeedsTime; // Flags that Sound Helper needs an Idle call
-
- Boolean gSoundIn = false; // Whether we can record
- short gRecorderState; // Record/playback state
-
- Boolean gBeatOn = false; // Beat sound on/off
- long gBeatRefNum; // Beat sound's reference number
- SndChannelPtr gBeatChannel; // The beat sound channel
-
- long gProgressCurrent; // Progress bar's current value
- long gProgressMin; // Progress bar's minimum value
- long gProgressMax; // Progress bar's maximum value
-
- Handle gUserSnd = nil; // Handle to user's recording (nil if none)
- long gUserSndRef; // Reference number of user's recording
- short gRecLevel; // Current recording level
- Boolean gRecDone; // Tells whether recording has completed
-
- DialogPtr gSHDialog; // Sound Helper dialog
-
- //=======================================================================================
- // Static prototypes
- //=======================================================================================
- static Boolean Init(SysEnvRec *env);
- static pascal void BoxItem(WindowPtr theWindow, short itemNum);
- static pascal void LevelItem(WindowPtr theWindow,short itemNum);
- static pascal void ProgressItem(WindowPtr theWindow,short itemNum);
- static void ProgressSetup(long min, long max, long value);
- static void Progress(DialogPtr dialog, short itemNum, long value, Boolean redraw);
- static Boolean SoundSetup(void);
- static void SetRecorderState(short newState);
- static Boolean DialogSetup(void);
- static void DialogIdle(void);
- static Boolean DialogHit(short item);
- static void SHDemo(void);
-
- //=======================================================================================
- Boolean Init(SysEnvRec *env)
- {
- short err;
- long response, inRefNum;
-
- // The usual Mac initialization stuff
- InitGraf(&qd.thePort);
- InitFonts();
- InitWindows();
- TEInit();
- InitDialogs(nil);
- InitCursor();
-
- MaxApplZone();
-
- err = SysEnvirons(2,env);
- if (!err && env->systemVersion >= kMinSystem) {
- if (Gestalt(gestaltSoundAttr, &response) == noErr &&
- (response >> gestaltSoundIOMgrPresent) & 0x01) {
- if (SPBOpenDevice(nil, siWritePermission, &inRefNum) == noErr) {
- SPBCloseDevice(inRefNum);
- gSoundIn = true;
- }
- }
- return(true);
- } else return(false);
- }
-
- //=======================================================================================
- pascal void BoxItem(WindowPtr theWindow, short itemNum)
- {
- short aType;
- Rect theBox;
- Handle aHandle;
-
- GetDItem(theWindow, itemNum, &aType, &aHandle, &theBox);
- PenNormal(); ForeColor(blackColor);
- FrameRect(&theBox);
- }
-
- //=======================================================================================
- pascal void LevelItem(WindowPtr theWindow,short itemNum)
- {
- short aType,endOfBox,totalBar;
- Rect theBox;
- Handle aHandle;
-
- GetDItem(theWindow,itemNum,&aType,&aHandle,&theBox);
- PenNormal(); ForeColor(blackColor);
- FrameRect(&theBox);
- InsetRect(&theBox,1,1);
- endOfBox = theBox.right;
- totalBar = theBox.right - theBox.left;
- theBox.right = theBox.left + ((gRecLevel * totalBar) / kNumRecLevelSteps);
- PenPat(&qd.dkGray); PaintRect(&theBox);
- theBox.left = theBox.right; theBox.right = endOfBox;
- EraseRect(&theBox);
- PenNormal();
- }
-
- //=======================================================================================
- pascal void ProgressItem(WindowPtr theWindow,short itemNum)
- {
- short aType,endOfBox,totalBar;
- long totalRange,normalValue;
- Rect theBox;
- Handle aHandle;
-
- GetDItem(theWindow,itemNum,&aType,&aHandle,&theBox);
- PenNormal(); ForeColor(blackColor);
- FrameRect(&theBox);
- InsetRect(&theBox,1,1);
- if (gProgressMin == 0 && gProgressMax == 0) {
- EraseRect(&theBox);
- } else {
- endOfBox = theBox.right;
- normalValue = gProgressCurrent - gProgressMin;
- totalRange = gProgressMax - gProgressMin;
- totalBar = theBox.right - theBox.left;
- theBox.right = theBox.left + ((normalValue * totalBar) / totalRange);
- PenPat(&qd.dkGray); PaintRect(&theBox);
- theBox.left = theBox.right; theBox.right = endOfBox;
- EraseRect(&theBox);
- }
- PenNormal();
- }
-
- //=======================================================================================
- void ProgressSetup(long min, long max, long value)
- {
- gProgressMin = min;
- gProgressMax = max;
- gProgressCurrent = value;
- }
-
- //=======================================================================================
- void Progress(DialogPtr dialog, short itemNum, long value, Boolean redraw)
- {
- gProgressCurrent = value;
- if (redraw)
- ProgressItem(dialog, itemNum);
- }
-
- //=======================================================================================
- Boolean SoundSetup(void)
- {
- short err;
- Handle snd;
-
- // Get a sound channel from the Helper by calling SHPlayByHandle with a nil handle.
- err = SHPlayByHandle(nil,&gBeatRefNum);
- if (err)
- return(false);
- else {
- err = SHGetChannel(gBeatRefNum,&gBeatChannel);
- if (err)
- return(false);
-
- snd = GetResource(soundListRsrc,kDanceBeat);
- if (snd) {
- err = SndPlay(gBeatChannel,snd,true); // FIX ME
- return(err ? false : true);
- } else return(false);
- }
- }
-
- //=======================================================================================
- void SetRecorderState(short newState)
- {
- Boolean rec, play, stop, pause;
- char blank = 0;
- Str255 parm0;
-
- switch (newState) {
- case kIdleNoSound:
- rec = gSoundIn;
- play = stop = pause = false;
- break;
- case kIdleSound:
- rec = gSoundIn;
- play = true;
- stop = pause = false;
- break;
- case kRecording:
- case kRecordPaused:
- case kPlaying:
- case kPlayPaused:
- stop = pause = true;
- rec = play = false;
- break;
- }
-
- if (rec)
- EnCtrl(gSHDialog, kRecordBtn);
- else DisCtrl(gSHDialog, kRecordBtn);
- if (play)
- EnCtrl(gSHDialog, kPlayBtn);
- else DisCtrl(gSHDialog, kPlayBtn);
- if (stop)
- EnCtrl(gSHDialog, kStopBtn);
- else DisCtrl(gSHDialog, kStopBtn);
- if (pause)
- EnCtrl(gSHDialog, kPauseBtn);
- else DisCtrl(gSHDialog, kPauseBtn);
-
- GetIndString(parm0, kStrs, kFirstStateStr + newState);
- ParamText(parm0, &blank, &blank, &blank);
- InvalItem(gSHDialog, kRecPlayStatus);
-
- if (newState != kRecording) {
- gRecLevel = 0;
- LevelItem(gSHDialog, kLevelBar);
- }
-
- gRecorderState = newState;
- }
-
- //=======================================================================================
- Boolean DialogSetup(void)
- {
- short item;
-
- gSHDialog = GetNewDialog(kSHDialog, nil, (WindowPtr)-1);
- if (gSHDialog == nil)
- return(false);
-
- // Set up dialog items
- SetPort(gSHDialog);
- for (item = 0; item < kNumBoxItems; item++)
- UserItem(gSHDialog, kFirstBoxItem + item, BoxItem);
- UserItem(gSHDialog, kProgressBar, ProgressItem);
- ProgressSetup(0, 0, 0);
- UserItem(gSHDialog, kLevelBar, LevelItem);
- SetRecorderState(kIdleNoSound);
- ShowWindow(gSHDialog);
- }
-
- //=======================================================================================
- void DialogIdle(void)
- {
- SHRecordStatusRec recStat;
- SHPlayStat playStatus;
-
- // Update the level meter if recording
- SetPort(gSHDialog);
- if (gRecorderState == kRecording) {
- SetPort(gSHDialog);
- SHRecordStatus(&recStat);
- Progress(gSHDialog, kProgressBar, recStat.currentRecordTime, true);
- gRecLevel = recStat.meterLevel;
- LevelItem(gSHDialog, kLevelBar);
- }
-
- // Notice when recording has stopped
- if ((gRecorderState == kRecording || gRecorderState == kRecordPaused) && gRecDone) {
- SetRecorderState(kIdleSound);
- SHGetRecordedSound(&gUserSnd);
- ProgressSetup(0, 0, 0);
- Progress(gSHDialog, kProgressBar, 0, true);
- }
-
- // Notice when playback has stopped
- playStatus = SHPlayStatus(gUserSndRef);
- if ((gRecorderState == kPlaying || gRecorderState == kPlayPaused) &&
- (playStatus == shpFinished || playStatus == shpError))
- SetRecorderState(kIdleSound);
- }
-
- //=======================================================================================
- Boolean DialogHit(short item)
- {
- Boolean done = false;
- short sndID,err;
- SndCommand cmd;
- SHRecordStatusRec recStat;
-
- // Handle dialog items
- SetPort(gSHDialog);
- switch (item) {
- case kQuit:
- done = true;
- break;
- case kAbout :
- Alert(kAboutAlert, nil);
- break;
- case kFillBtn:
- case kHitBtn:
- sndID = (item == kFillBtn) ? kFillSnd : kHitSnd;
- err = SHPlayByID(sndID, nil);
- if (err == kSHErrOutaChannels)
- StopAlert(kOutaChannelsAlert, nil);
- else if (err)
- ErrorExtra(kPlayError, err);
- break;
- case kBeatCheck:
- gBeatOn = !gBeatOn;
- SetValue(gSHDialog, kBeatCheck, gBeatOn);
- cmd.param1 = 0;
- if (gBeatOn) {
- cmd.cmd = freqCmd;
- cmd.param2 = kMiddleC;
- } else {
- cmd.cmd = quietCmd;
- cmd.param2 = 0;
- }
- SndDoImmediate(gBeatChannel,&cmd); // ignore error
- break;
- case kRecordBtn:
- if (gRecorderState == kIdleSound || gRecorderState == kIdleNoSound) {
- if (gRecorderState == kIdleSound && gUserSnd != nil) {
- DisposHandle(gUserSnd);
- gUserSnd = nil;
- }
- err = SHRecordStart(kMaxUserRecording, 'best', &gRecDone);
- if (err)
- ErrorExtra(kRecordError, err);
- else {
- SetRecorderState(kRecording);
- SHRecordStatus(&recStat);
- ProgressSetup(0, recStat.totalRecordTime,
- recStat.currentRecordTime);
- }
- } else SysBeep(10);
- break;
- case kPlayBtn:
- if (gRecorderState == kIdleSound && gUserSnd != nil) {
- err = SHPlayByHandle(gUserSnd, &gUserSndRef);
- if (err == noErr)
- SetRecorderState(kPlaying);
- else if (err == kSHErrOutaChannels)
- StopAlert(kOutaChannelsAlert, nil);
- else if (err)
- ErrorExtra(kPlayError, err);
- } else SysBeep(10);
- break;
- case kStopBtn:
- if (gRecorderState == kPlaying || gRecorderState == kPlayPaused)
- SHPlayStop(gUserSndRef);
- else if (gRecorderState == kRecording || gRecorderState == kRecordPaused)
- SHRecordStop();
- else SysBeep(10);
- break;
- case kPauseBtn:
- switch (gRecorderState) {
- case kRecording:
- SHRecordPause();
- SetRecorderState(kRecordPaused);
- break;
- case kRecordPaused:
- SHRecordContinue();
- SetRecorderState(kRecording);
- break;
- case kPlaying:
- SHPlayPause(gUserSndRef);
- SetRecorderState(kPlayPaused);
- break;
- case kPlayPaused:
- SHPlayContinue(gUserSndRef);
- SetRecorderState(kPlaying);
- break;
- default:
- SysBeep(10);
- break;
- }
- break;
- }
-
- return(done);
- }
-
- //=======================================================================================
- void SHDemo(void)
- {
- GrafPtr oldPort;
- DialogPtr dlg;
- short itemHit;
- EventRecord event;
- Boolean done = false;
-
- // Initialize Helper
- if (SHInitSoundHelper(&gHelperNeedsTime, kMaxChannels) != noErr) {
- ErrorAlert(kCantInitSH);
- return;
- }
-
- // Set up the beat box sound channel
- if (!SoundSetup()) {
- ErrorAlert(kCantGetChannel);
- SHKillSoundHelper();
- return;
- }
-
- // Save port and set up the main dialog
- GetPort(&oldPort);
- if (!DialogSetup())
- return;
-
- // Our little event loop
- do {
- // Give the Sound Helper an SHIdle call if it needs one
- if (gHelperNeedsTime)
- SHIdle();
-
- // Update the level meter if recording
- DialogIdle();
-
- // Get events and handle the dialog
- WaitNextEvent(everyEvent, &event, 0, nil);
- if (IsDialogEvent(&event) && DialogSelect(&event, &dlg, &itemHit))
- done = DialogHit(itemHit);
- } while (!done);
-
- // Lose the dialog
- DisposeDialog(gSHDialog);
- SetPort(oldPort);
-
- // Kill the Helper
- SHKillSoundHelper();
- }
-
- //=======================================================================================
- main()
- {
- SysEnvRec env;
-
- if (Init(&env))
- SHDemo(); // Knock yourself out!
- else ErrorAlert(kBadEnv);
- }
-